package com.wxc.config.shiro;


import com.wxc.contants.Constant;
import com.wxc.service.RedisService;
import com.wxc.utils.token.JwtTokenUtil;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author wxc
 * @date 2021年10月24日 22:03
 */
@Component
public class RedisCache<K, V> implements Cache<K, V> {

    @Autowired
    private RedisService redisService;


    private String getCacheKey(Object token) {
        if (token == null) return null;
        String userId = JwtTokenUtil.getUserId(token.toString());
        return Constant.IDENTIFY_CACHE_KEY + userId;
    }

    /**
     * @date 2021/10/25 9:52
     * @param key
     * @return V
     * 哪怕用户有很多token redis存储的格式都是 shiro-cache_用户id,所以不会存很多次
     * 在这里可以对缓存进行一个刷新或延期
     */
    @Override
    public V get(K key) throws CacheException {
        String cacheKey = getCacheKey(key);
        return (V) redisService.get(cacheKey);
    }

    @Override
    public V put(K key, V v) throws CacheException {
        String cacheKey = getCacheKey(key);
        V value = (V) redisService.get(cacheKey);
        redisService.set(cacheKey, v, 1, TimeUnit.DAYS);
        return value;
    }

    @Override
    public V remove(K key) throws CacheException {
        String cacheKey = getCacheKey(key);
        V value = (V) redisService.get(cacheKey);
        redisService.delete(cacheKey);
        return value;
    }

    @Override
    public void clear() throws CacheException {
        Set<String> keys = redisService.keys(Constant.IDENTIFY_CACHE_KEY + "*");
        if (CollectionUtils.isEmpty(keys)) return;
        for (String key : keys) {
            redisService.delete(key);
        }
    }

    @Override
    public int size() {
        Set<String> keys = redisService.keys(Constant.IDENTIFY_CACHE_KEY + "*");
        return keys == null ? 0 : keys.size();
    }

    /**
     * @date 2021/10/25 9:35
     * @return java.util.Set<K>
     * 这个方法其实有问题 (K) key是转换不了的
     */
    @Override
    public Set<K> keys() {
        Set<String> keys = redisService.keys(Constant.IDENTIFY_CACHE_KEY + "*");
        if (CollectionUtils.isEmpty(keys)) return Collections.emptySet();

        Set<K> convertedKeys = new HashSet<>();
        for (String key:keys) {
            convertedKeys.add((K) key);
        }
        return convertedKeys;
    }

    @Override
    public Collection<V> values() {
        Set<String> keys = redisService.keys(Constant.IDENTIFY_CACHE_KEY + "*");
        List<V> values = new ArrayList<>(keys.size());
        for (String key : keys) {
            values.add((V) redisService.get(key));
        }
        return Collections.unmodifiableList(values);
    }
}
